package admin_permissions

import (
	"fmt"
	"gitee.com/theegg/go-brick/app/model"
	"gitee.com/theegg/go-brick/app/model/admin/admin_role_permissions"
	"gitee.com/theegg/go-brick/app/model/admin/admin_user_permissions"
	"gitee.com/theegg/go-brick/app/service/app"
)

// 返回的数据结构 == checkbox
type PermissionsCheckData struct {
	Id       int64                   `json:"id"`
	Label    string                  `json:"label"`
	Children []*PermissionsCheckData `json:"children"`
}

// 返回的数据结构 == select
type PermissionsSelectData struct {
	Value    int64                    `json:"value"`
	Label    string                   `json:"label"`
	Children []*PermissionsSelectData `json:"children"`
}

// 返回的数据结构 列表树
type PermissionsListTreeData struct {
	Id         int64
	Route      string
	Name       string
	HttpMethod string
	Sign       string
	Level      int
	Pid        int64
	Children   []*PermissionsListTreeData
}

// 查询参数
type AdminPermissionQueryParams struct {
	PageSize  string `form:"page_size" binding:"gte=0,lte=100" label:"每页数量"`
	PageIndex string `form:"page_index" binding:"gte=0,lte=99999" label:"当前页数"`
	Route     string `form:"route" binding:"" label:"路由"`
	Name      string `form:"name" binding:"" label:"名称"`
}

// 添加参数
type AdminPermissionAddParams struct {
	Pid        int64  `form:"pid" binding:"gte=0,lte=9999999" label:"上级"`
	Name       string `form:"name" binding:"customMin=6,customMax=64" label:"名称"`
	Route      string `form:"route" binding:"customMin=6,customMax=64" label:"路由"`
	HttpMethod string `form:"http_method" binding:"customMin=3,customMax=64" label:"HTTP方法"`
	Slug       string `form:"slug" binding:"required,customMin=6,customMax=64" label:"标识"`
}

// 最大层级
const MAX_LEVEL = 3

// 禁止删除的路由
var cantDeleteRoute = []string{"/mpi/develop/permission/detail", "/mpi/develop/permission/add", "/mpi/develop/permission/list"}

// 分页获取所有数据 只能看到自己拥有的权限  角色权限 + 个人权限
// @param params map 参数
// @param pageSize int 每页数据量
// @return mix
func GetDataList(params map[string]interface{}, permissionIds []int64) (map[string]interface{}, error) {
	returnData := make(map[string]interface{})

	queryParams, err := model.BuildAdminQueryParam(params)
	if err != nil {
		return returnData, nil
	}

	items := make([]*AdminPermissions, 0)
	query := app.Db().Desc("id").In("id", permissionIds)

	isSearch := false
	// 路由
	if _, ok := queryParams.Params["route"]; ok && queryParams.Params["route"] != "" {
		isSearch = true
		query.And("route like ?", "%"+queryParams.Params["route"].(string)+"%")
	}

	// 名称
	if _, ok := queryParams.Params["name"]; ok && queryParams.Params["name"] != "" {
		isSearch = true
		query.And("name like ?", "%"+queryParams.Params["name"].(string)+"%")
	}

	// 查询多条数据
	errQuery := query.Find(&items)
	if errQuery != nil {
		return nil, errQuery
	}

	if isSearch {
		returnData["data"] = items
	} else {
		returnData["data"] = BuildPermissionListTree(items, 0, 3)
	}

	return returnData, nil
}

// 获取数据 通过ID
func GetItemById(id int64) (*AdminPermissions, error) {
	item := new(AdminPermissions)

	has, err := app.Db().ID(id).Get(item)

	if err != nil {
		return nil, err
	} else {
		if !has {
			return item, nil
		}
	}

	return item, nil
}

// 添加后 or 更新item
func (ap *AdminPermissions) AddOrUpdateItem(params AdminPermissionAddParams, parent *AdminPermissions) error {
	var affected int64
	var err error

	if ap != nil && ap.Id > 0 {
		// 1. 检测 route 的唯一性
		if ap.Route != params.Route {
			if ok, errRoute := checkFieldUnique("route", params.Route); !ok || errRoute != nil {
				return app.NewError("对不起, 路由已经存在")
			}
		}

		// 2. 检测 sign 的唯一性
		if ap.Sign != params.Slug {
			if ok, errRoute := checkFieldUnique("sign", params.Slug); !ok || errRoute != nil {
				return app.NewError("对不起, 标识已经存在")
			}
		}

		// 更新数据
		updateData := AdminPermissions{
			Name:       params.Name,
			Route:      params.Route,
			Sign:       params.Slug,
			HttpMethod: params.HttpMethod,
		}

		// 3. 如果切换上级
		if ap.Pid != params.Pid {
			// 更改上级ID
			updateData.Pid = params.Pid
		}

		affected, err = app.Db().ID(ap.Id).Cols("name", "pid", "route", "http_method", "updated_at").Update(updateData)

		if err != nil {
			return err
		}

		if affected != 1 {
			return app.NewError("对不起, 更新出错(ap-aui)")
		}

		// 4. 更新缓存
		FlushCacheByTag()

	} else {
		// 1. 检测 route 的唯一性
		if ok, errRoute := checkFieldUnique("route", params.Route); !ok || errRoute != nil {
			return app.NewError("对不起, 路由已经存在")
		}

		// 2. 检测 sign 的唯一性
		if ok, errRoute := checkFieldUnique("sign", params.Slug); !ok || errRoute != nil {
			return app.NewError("对不起, 标识已经存在")
		}

		// 3. 计算级别
		var level int
		if parent == nil {
			level = 1
		} else {
			level = parent.Level + 1
		}

		// 4. 组装插入数据
		ap.Level = level
		ap.Name = params.Name
		ap.Sign = params.Slug
		ap.Status = 1

		// 顶级不需要
		if parent != nil {
			ap.Pid = params.Pid
			ap.Route = params.Route
			ap.HttpMethod = params.HttpMethod
		}

		// 开启事务
		session := app.Db().NewSession()
		defer session.Close()
		errSb := session.Begin()
		if errSb != nil {
			return app.NewError(errSb)
		}

		affected, err = session.Insert(ap)

		if err != nil {
			return err
		}

		if affected != 1 {
			return app.NewError("新增权限错误(0x001)")
		}

		// 5. 更新缓存
		ok := FlushCacheByTag()
		if !ok {
			return app.NewError("对不起, 刷新缓存失败")
		}

		// 提交
		errCommit := session.Commit()
		if errCommit != nil {
			return app.NewError(errCommit)
		}
	}

	return nil
}

// 删除管理员权限
func DeleteAdminPermission(permissionId int64) (bool, error) {

	// 检测是否在忽略的路由
	itemCheck := new(AdminPermissions)
	count, errCheck := app.Db().In("route", cantDeleteRoute).And("id = ?", permissionId).Count(itemCheck)
	if errCheck != nil {
		return false, errCheck
	}

	if count > 0 {
		return false, fmt.Errorf("对不起, 路由无法删除")
	}

	/* =============  开启事务 ============ */
	// 1.删除ID
	// 2.删除role_permission
	// 3.删除user_permission

	session := app.Db().NewSession()
	defer session.Close()
	errSb := session.Begin()
	if errSb != nil {
		return false, app.NewError(errSb)
	}

	// 删除ID
	item := new(AdminPermissions)
	_, err := session.ID(permissionId).Delete(item)
	if err != nil {
		session.Rollback()
		return false, err
	}

	// 删除role_permission
	itemRole := new(admin_role_permissions.AdminRolePermissions)
	_, errRole := session.Where("permission_id = ?", permissionId).Delete(itemRole)
	if errRole != nil {
		session.Rollback()
		return false, errRole
	}

	// 删除user_permission
	itemUser := new(admin_user_permissions.AdminUserPermissions)
	_, errUser := session.Where("permission_id = ?", permissionId).Delete(itemUser)
	if errUser != nil {
		session.Rollback()
		return false, errUser
	}

	// 提交
	errCommit := session.Commit()
	if errCommit != nil {
		return false, errCommit
	}

	return true, nil
}

// @title BuildPermissionListTree
// @description 构建 权限的上下级 关系树 用在列表页
// @mark  关于递归深度的问题
func BuildPermissionListTree(sourceData []*AdminPermissions, pid int64, levelArgs ...int) []*PermissionsListTreeData {
	deep := 3
	if len(levelArgs) > 0 {
		deep = levelArgs[0]
	}

	deep--

	buildData := make([]*PermissionsListTreeData, 0)

	for _, item := range sourceData {
		if item.Pid == pid {
			data := PermissionsListTreeData{
				Id:         item.Id,
				Name:       item.Name,
				Route:      item.Route,
				Sign:       item.Sign,
				HttpMethod: item.HttpMethod,
				Level:      item.Level,
				Pid:        item.Pid,
				Children:   make([]*PermissionsListTreeData, 0),
			}

			if deep > 0 {
				data.Children = BuildPermissionListTree(sourceData, item.Id, deep)
			}

			buildData = append(buildData, &data)
		}
	}

	return buildData
}

// @title BuildPermissionTree
// @description 构建 权限的下级 关系树 三级结构
func BuildPermissionTree(sourceData map[int64]*AdminPermissions, pid int64, levelArgs ...int) []*PermissionsCheckData {
	deep := 3
	if len(levelArgs) > 0 {
		deep = levelArgs[0]
	}

	deep--

	buildData := make([]*PermissionsCheckData, 0)

	for _, item := range sourceData {
		data := PermissionsCheckData{
			Id:       item.Id,
			Label:    item.Name,
			Children: make([]*PermissionsCheckData, 0),
		}

		if item.Pid == pid {
			if deep > 0 {
				data.Children = BuildPermissionTree(sourceData, item.Id, deep)
			}
			buildData = append(buildData, &data)
		}
	}

	return buildData
}

// @title BuildPermissionSelectTree
// @description 构建 权限的上下级联动 关系树 N级结构 默认三级
func BuildPermissionSelectTree(sourceData map[int64]*AdminPermissions, pid int64, levelArgs ...int) []*PermissionsSelectData {
	deep := 3
	if len(levelArgs) > 0 {
		deep = levelArgs[0]
	}

	deep--

	buildData := make([]*PermissionsSelectData, 0)

	for _, item := range sourceData {
		data := PermissionsSelectData{
			Value:    item.Id,
			Label:    item.Name,
			Children: make([]*PermissionsSelectData, 0),
		}

		if item.Pid == pid {
			if deep > 0 {
				data.Children = BuildPermissionSelectTree(sourceData, item.Id, deep)
			}
			buildData = append(buildData, &data)
		}
	}

	return buildData
}

// @title 从数据库获取所有的  指定管理角色　分配的权限
// @return map[int64]*AdminPermissions
func GetAdminPermissionsByRoleIdFromDb(roleId int64, superRoleOptions ...bool) (map[int64]*AdminPermissions, error) {
	isSupperRole := false
	if len(superRoleOptions) > 0 && superRoleOptions[0] {
		isSupperRole = true
	}

	// 获取对象
	adminPermissions := make(map[int64]*AdminPermissions)

	if !isSupperRole {
		adminRolePermissions := make(map[int64]*admin_role_permissions.AdminRolePermissions)

		err := app.Db().Where("role_id = ?", roleId).Find(&adminRolePermissions)

		if err != nil {
			return nil, app.NewError(err)
		}

		// 所有的IDS
		ids := make([]int64, 0)
		for _, k := range adminRolePermissions {
			ids = append(ids, k.PermissionId)
		}

		// 如果没有数据
		if len(ids) == 0 {
			return adminPermissions, nil
		}

		errPer := app.Db().In("id", ids).Where("status = ?", 1).Find(&adminPermissions)
		if errPer != nil {
			return nil, app.NewError(errPer)
		}
	} else {
		// 超级角色　不需要配置
		errPer := app.Db().Where("status = ?", 1).Find(&adminPermissions)
		if errPer != nil {
			return nil, app.NewError(errPer)
		}
	}

	return adminPermissions, nil
}

// @title 从数据库获取所有的  指定管理员　分配的权限
// @return map[int64]*AdminPermissions
func GetAdminPermissionsByUserIdFromDb(userId int64, isSuperUser ...bool) (map[int64]*AdminPermissions, error) {
	if len(isSuperUser) > 0 && isSuperUser[0] {
		adminPermissions := make(map[int64]*AdminPermissions)
		errPer := app.Db().Find(&adminPermissions)
		if errPer != nil {
			return nil, app.NewError(errPer)
		}
		return adminPermissions, nil
	}

	adminUserPermissions := make(map[int64]*admin_user_permissions.AdminUserPermissions)

	err := app.Db().Where("user_id = ?", userId).Find(&adminUserPermissions)

	if err != nil {
		return nil, app.NewError(err)
	}

	// 获取对象
	adminPermissions := make(map[int64]*AdminPermissions)

	// 所有的IDS
	ids := make([]int64, 0)
	for _, k := range adminUserPermissions {
		ids = append(ids, k.PermissionId)
	}

	// 如果没有数据
	if len(ids) == 0 {
		return adminPermissions, nil
	}

	errPer := app.Db().In("id", ids).Find(&adminPermissions)
	if errPer != nil {
		return nil, app.NewError(errPer)
	}

	return adminPermissions, nil
}

/** =============================  辅助函数 ============================= */

// 检测字段唯一性 如果存在返回false, 不存在返回true
func checkFieldUnique(field string, value interface{}) (bool, error) {
	user := new(AdminPermissions)

	has, err := app.Db().Where(field+" = ?", value).Get(user)

	if err != nil {
		return false, err
	} else {
		if has {
			return false, nil
		}
	}

	return true, nil
}
